package com.zhangcuishan.blog.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.zhangcuishan.blog.pojo.ChatGpt3dot5Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.*;
import org.springframework.util.*;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Arrays;
import java.util.HashMap;

@RequestMapping({"/chatbot"})
@RestController
@CrossOrigin
public class ChatBotController {
    private static final Logger log = LoggerFactory.getLogger(com.zhangcuishan.blog.controller.ChatBotController.class);

    @Autowired
    public RestTemplate restTemplate;

    @Value("${openai.apiKey}")
    private String OPEN_API_KEY;

    @Value("${api.asr}")
    private String API_ASR;

    @RequestMapping({"/upload"})
    @ResponseBody
    public Object sendRequest(@RequestParam("file") MultipartFile multipartFile) throws IOException {
        String originalFilename = multipartFile.getOriginalFilename();
        String fileType = multipartFile.getContentType();
        HttpHeaders requestHeaders = new HttpHeaders();
        requestHeaders.add("appCode", "platform-device");
        requestHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
        LinkedMultiValueMap linkedMultiValueMap = new LinkedMultiValueMap();
        String fileName = multipartFile.getOriginalFilename();
        Assert.notNull(fileName, "");
        File file = new File(fileName);
        try (OutputStream out = new FileOutputStream(file)) {
            FileCopyUtils.copy(multipartFile.getInputStream(), out);
        } catch (IOException e) {
            log.info(""+ e.getMessage());
        }
        FileSystemResource resource = new FileSystemResource(file);
        linkedMultiValueMap.add("file", resource);
        if (multipartFile.isEmpty())
            return "false";
        String fileName1 = multipartFile.getOriginalFilename();
//        File dest = new File((new File("F:")).getAbsolutePath() + "/" + fileName1);
//        if (!dest.getParentFile().exists())
//            dest.getParentFile().mkdirs();
//        try {
//            multipartFile.transferTo(dest);
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        System.out.println("Done");
        HttpEntity<MultiValueMap> requestEntity = new HttpEntity(linkedMultiValueMap, (MultiValueMap)requestHeaders);
        ResponseEntity<HashMap> responseEntity = this.restTemplate.postForEntity(API_ASR, requestEntity, HashMap.class, new Object[0]);
        System.out.println("responseEntity = " + responseEntity);
        Object result = ((HashMap)responseEntity.getBody()).get("result");
        System.out.println("result = " + result);
        return responseEntity.getBody();
    }

    @PostMapping({"/conversation"})
    public void conversation(@RequestBody String prompt, HttpServletResponse httpServletResponse) throws IOException {
        httpServletResponse.setContentType("text/plain; charset=UTF-8");
        UriComponentsBuilder builder = UriComponentsBuilder.fromUriString("https://api.openai.com/v1/chat/completions").queryParams(null);
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.setContentType(MediaType.APPLICATION_JSON);
        httpHeaders.setBearerAuth(this.OPEN_API_KEY);
        String json = getRequestBody(prompt);
        HttpEntity<Object> requestEntity = new HttpEntity(json, (MultiValueMap)httpHeaders);
        ResponseEntity<Resource> responseEntity = this.restTemplate.exchange(builder.build().toUriString(), HttpMethod.POST, requestEntity, Resource.class, new Object[0]);
        PrintWriter writer = httpServletResponse.getWriter();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(((Resource)responseEntity.getBody()).getInputStream()));
            String line;
            while ((line = bufferedReader.readLine()) != null && !"data: [DONE]".equals(line)) {
                String message = getMessageFromLine(line, "data: ");
                writer.write(message);
                writer.flush();
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String getMessageFromLine(String line, String prefix) throws JsonProcessingException {
        if (!StringUtils.hasLength(line.trim()))
            return "";
        String messageJsonStr = line.substring(line.indexOf(prefix) + prefix.length());
        ObjectMapper objectMapper = new ObjectMapper();
        ObjectNode objectNode = (ObjectNode)objectMapper.readTree(messageJsonStr);
        JsonNode messageNode = objectNode.get("choices").get(0).get("delta").get("content");
        if (messageNode != null)
            return messageNode.asText();
        return "";
    }

    private String getRequestBody(String prompt) throws JsonProcessingException {
        ChatGpt3dot5Request chatGpt3dot5Request = new ChatGpt3dot5Request();
        chatGpt3dot5Request.setStream(Boolean.valueOf(true));
        chatGpt3dot5Request.setMessages(Arrays.asList(new ChatGpt3dot5Request.Message[] { new ChatGpt3dot5Request.Message("user", prompt) }));
        ObjectMapper objectMapper = new ObjectMapper();
        String json = objectMapper.writeValueAsString(chatGpt3dot5Request);
        return json;
    }
}
